/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sirtet.tetris;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import sirtet.GameAction;
import sirtet.GameBoard;
import sirtet.Player;
import sirtet.event.BoardActionEvent;
import sirtet.event.BoardBlocksEliminatedEvent;
import sirtet.event.BoardEvent;
import sirtet.event.BoardListener;
import sirtet.event.BoardPieceEvent;
import sirtet.event.BoardPieceFixedEvent;

/**
 * A player who send periodic FALL action to force piece falling
 * @author guangwei.zhu
 */
public final class FallEnforcer extends Player implements BoardListener {

    protected Timer currentInvoker;

    protected class DelayInvoker implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (getEnabled()) {
                invoke();
            }
        }
    }

    public FallEnforcer() {
        this(500);
    }

    public FallEnforcer(int interval) {
        super("", TetrisBoard.GAMETYPE, false);      // Anonymous player

        currentInvoker = new Timer(interval, new DelayInvoker());
        this.setInterval(interval);
        currentInvoker.setRepeats(true);
        currentInvoker.start();
    }

    public FallEnforcer(String playerID, int interval) {
        super(playerID, TetrisBoard.GAMETYPE, false);

        currentInvoker = new Timer(interval, new DelayInvoker());
        currentInvoker.setRepeats(true);
        currentInvoker.start();
    }

    public void setInterval(int interval) {
        if (interval <= 0) {
            throw new IllegalArgumentException();
        }

        currentInvoker.setDelay(interval);
    }

    public synchronized void invoke() {
        invokeAction(new GameAction(this.id(), TetrisAction.FALL));
    }

    public void boardChanged(BoardEvent evt) {      // Do nothing
    }

    public void boardGameOver(BoardEvent evt) {     // Do nothing
    }

    public void boardStarted(BoardEvent evt) {      // Do nothing
    }

    public void boardReset(BoardEvent evt) {        // Do nothing
    }

    public void boardPieceFixed(BoardPieceFixedEvent evt) {     // Do nothing
    }

    public void boardNextPieceChanged(BoardPieceEvent evt) {    // Do nothing
    }

    public void boardBlocksEliminated(BoardBlocksEliminatedEvent evt) { // Do nothing
    }

    public void boardDisposing(BoardEvent evt) {     // Do nothing
    }

    @Override
    public void bindBoard(GameBoard board) {
        super.bindBoard(board);
        board.addBoardListener(this);
    }

    @Override
    public void unbindBoard(GameBoard board) {
        super.unbindBoard(board);
        board.removeBoardListener(this);
    }

    public void boardActionTriggered(BoardActionEvent evt) {
        // Bypass FALL actions sent by this FallEnforcer
        if (evt.action.actor.equals(this.id())) {
            return;
        }

        // We need to "reset" the timer which controls the interval
        if (evt.action.command.equals(TetrisAction.FALL)) {
            currentInvoker.restart();
        }
    }
}
